package com.jt.blog.service.impl;

import com.jt.blog.dao.TagMapper;
import com.jt.blog.domain.Tag;
import com.jt.blog.service.TagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;

@Service
public class TagServiceImpl implements TagService {
    //RedisAutoConfiguration 类中做的RedisTemplate的配置
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TagMapper tagMapper;



    @Cacheable(value = "tagCache")
    @Override
    public List<Tag> selectTags() {
        return tagMapper.selectList(null);
    }

    @Cacheable(value = "tagCache",key = "#root.targetClass.name")
    @Override
    public Tag insertTag(Tag tag) {
        tagMapper.insert(tag);
        return tag;
    }

    /**
     * 向数据库中在添加一个新的标签
     * @param tag
     * 思考：假如这里做了insert操作后，数据库中的数据更新了
     *  也要更新redis缓存，你有什么方案？
     *  方案一：不更新redis，等redis的key失效后，自动更新
     *  方案二：执行完insert，删除redis指定的key对应的数据
     *  方案三：执行完insert，更新redis指定的key对应的内容
     * 说明：
     *  @CacheEvict 注解的作用是定义切入点方法，执行次注解描述的方法时，
     *  底层通过AOP方法执行redis数据的清除操作
     */
//    @CacheEvict(value = "tagCache",
//            allEntries = true, //删除key对应的所有数据
//            beforeInvocation = false)//执行insert之后，删除
//    @Override
//    public void insertTag(Tag tag) {
//        tagMapper.insert(tag);
//    }


    @CachePut(value = "tagCache",key = "#tag.id")
    @Override
    public Tag updateTag(Tag tag) {

        tagMapper.updateById(tag);
        return tag;

    }


    @Cacheable(value = "tagCache",key = "#id")
    @Override
    public Tag selectById(Long id){
        //...
        return tagMapper.selectById(id);
    }

    /**
     *@CachePut 注解描述的方法为一个缓存切入点方法，
     * 系统底层在执行此注解描述的方法时，可以对缓存数据执行更新操作，
     * （底层会先基于key获取值，然后对值进行修改）
     * @param tag
     */
//    @CachePut
//    @Override
//    public void insertTag(Tag tag) {
//
//        tagMapper.insert(tag);
//
//    }

//    @CacheEvict(value = "tagCache",
//                 allEntries = true, //删除key对应的所有数据
//                beforeInvocation = false)//执行insert之后，删除
//    @Override
//    public void insertTag(Tag tag) {
//
//        System.out.println("insert.before="+tag);
//        tagMapper.insert(tag);
//        System.out.println("insert.after="+tag);
//
//        ValueOperations vo = redisTemplate.opsForValue();
//        List<LinkedHashMap> list =
//                (List<LinkedHashMap>) vo.get("tagCache::com.jt.blog.service.impl.TagServiceImpl::selectTags");
//
//        System.out.println("o="+list);
//        LinkedHashMap map = new LinkedHashMap();
//        map.put("id", tag.getId());
//        map.put("name", tag.getName());
//        list.add(map);
//        vo.set("tagCache::com.jt.blog.service.impl.TagServiceImpl::selectTags", list);


    }


//    @Override
//    public List<Tag> selectTags() {
//
//        System.out.println("service.selectTags()");
//        //Long before = System.currentTimeMillis();
//
//        //1.从redis查询Tag信息，redis有则直接返回
//        ValueOperations<String, List<Tag>> valueOperations =
//                redisTemplate.opsForValue();
//
////        ValueOperations<Object, Object> valueOperations =
////                redisTemplate.opsForValue();
//
//        List<Tag> tags = valueOperations.get("tags");
//        // List<Tag> tags = (List<Tag>) valueOperations.get("tags");
//        //System.out.println("tags="+tags);
//
//        // Long after = System.currentTimeMillis();
//        // System.out.println("mysql.time="+(after-before));
//
//        if (tags != null && tags.isEmpty()) return tags;
//
//        //2.从redis没有获取tag信息，查询mysql
//        //System.out.println(" == select Tags from mysql == ");
//        //List<Tag> dbTags = tagMapper.selectList(null);
//        tags = tagMapper.selectList(null);
//
//        //3.将从mysql查询到tag信息存储到redis
//        //valueOperations.set("tags", dbTags);
//        valueOperations.set("tags", tags);
//
//        //4.返回查询结果
//        //return dbTags;
//        // after = System.currentTimeMillis();
//        // System.out.println("mysql.time="+(after-before));
//        return tags;
//    }

